package com.ruihu.admin.module.business.task.manager;

import cn.hutool.core.util.BooleanUtil;
import cn.hutool.core.util.StrUtil;
import com.ruihu.admin.common.domain.ResponseDTO;
import com.ruihu.admin.constant.CommonConst;
import com.ruihu.admin.module.business.log.interfacelog.dao.InterfaceLogDao;
import com.ruihu.admin.module.business.log.interfacelog.domain.dto.InterfaceLogQueryDTO;
import com.ruihu.admin.module.business.task.constant.TaskStatusEnum;
import com.ruihu.admin.module.business.task.dao.ElectricCoreDataDao;
import com.ruihu.admin.module.business.task.dao.SubTaskDao;
import com.ruihu.admin.module.business.task.dao.TaskDao;
import com.ruihu.admin.module.business.task.domain.dto.SubTaskQueryDTO;
import com.ruihu.admin.module.business.task.domain.entity.SubTaskEntity;
import com.ruihu.admin.module.business.task.domain.entity.TaskEntity;
import com.ruihu.admin.module.business.tasknode.dao.NodeInstProcessRelationDao;
import com.ruihu.admin.module.business.tasknode.dao.SubTaskNodeInstDao;
import com.ruihu.admin.module.business.tasknode.dao.TaskNodeFileDao;
import com.ruihu.admin.module.business.tasknode.domain.dto.SubTaskNodeInstAddDTO;
import com.ruihu.admin.module.business.tasknode.domain.dto.SubTaskNodeInstQueryDTO;
import com.ruihu.admin.module.business.tasknode.domain.entity.SubTaskNodeInstEntity;
import com.ruihu.admin.module.business.tasknode.service.AIInterfaceService;
import com.ruihu.admin.third.ApplicationContext;
import com.ruihu.admin.util.RequestTokenUtil;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.SetOperations;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.Date;
import java.util.List;
import java.util.Objects;
import java.util.stream.Collectors;

@Service
public class SubTaskManager {

    @Autowired
    private SubTaskNodeInstDao subTaskNodeInstDao;

    @Autowired
    private TaskDao taskDao;

    @Autowired
    private SubTaskDao subTaskDao;

    @Autowired
    private ElectricCoreDataDao electricCoreDataDao;

    @Autowired
    private TaskNodeFileDao taskNodeFileDao;

    @Autowired
    private NodeInstProcessRelationDao nodeInstProcessRelationDao;

    @Autowired
    private AIInterfaceService aiInterfaceService;

    @Autowired
    private SetOperations<String, Object> setOperations;

    /**
     * 清空子任务
     * @param subTaskEntity
     * @return
     */
    @Transactional(rollbackFor = Exception.class)
    public ResponseDTO<String> resetSubTask(SubTaskEntity subTaskEntity) {
        SubTaskNodeInstQueryDTO queryDTO = new SubTaskNodeInstQueryDTO();
        queryDTO.setSubTaskId(subTaskEntity.getId());
        List<SubTaskNodeInstEntity> subTaskNodeInstEntityList = this.subTaskNodeInstDao.queryList(queryDTO);
        List<Long> subTaskNodeInstIdList = subTaskNodeInstEntityList.stream().map(SubTaskNodeInstEntity::getId).collect(Collectors.toList());
        // 删除任务环节实例
        this.subTaskNodeInstDao.deleteBySubTaskId(subTaskEntity.getId());
        // 删除附件表
        this.taskNodeFileDao.deleteBySubTaskId(subTaskEntity.getId());
        // 删除导出数据表
        this.electricCoreDataDao.deleteBySubTaskId(subTaskEntity.getId());
        // 删除环节元素实例表
        if (subTaskNodeInstIdList.size() > 0)
            this.nodeInstProcessRelationDao.deleteBySubTaskNodeInstIdList(subTaskNodeInstIdList);
        // 判断是否有和AI的电芯编码请求未清除，若有发送清除消息
        if (ApplicationContext.isProductEnvironment()) {
            this.aiInterfaceService.sendElectricCoreClearMessage(subTaskEntity);
        }
        // 更新子任务
        String oldElectricCoreCode = subTaskEntity.getElectricCoreCode();
        subTaskEntity.setElectricCoreCode(null);
        subTaskEntity.setElectricCoreType(null);
        subTaskEntity.setStatus(TaskStatusEnum.CREATED.getValue());
        subTaskEntity.setCurrentTaskNodeInstId(null);
        subTaskEntity.setUpdateBy(RequestTokenUtil.getRequestUser().getRequestUserId());
        subTaskEntity.setUpdateTime(new Date());
        subTaskEntity.setCompletionTime(null);
        this.subTaskDao.updateById(subTaskEntity);
        this.setOperations.remove(CommonConst.REDIS_ELECTRIC_CORE_CODE_SET_NAME, oldElectricCoreCode);

        // 如果主任务状态已经为完成，则更新为运行状态
        TaskEntity taskEntity = this.taskDao.selectById(subTaskEntity.getMainTaskId());
        if (Objects.nonNull(taskEntity) && TaskStatusEnum.COMPLETE.getValue().equals(taskEntity.getStatus())) {
            taskEntity.setStatus(TaskStatusEnum.RUNNING.getValue());
            taskEntity.setUpdateBy(RequestTokenUtil.getRequestUser().getRequestUserId());
            taskEntity.setUpdateTime(new Date());
            this.taskDao.updateById(taskEntity);
        }
        return ResponseDTO.succ();
    }

    /**
     * 删除子任务
     * @param subTaskEntity
     * @return
     */
    @Transactional(rollbackFor = Exception.class)
    public ResponseDTO<String> deleteSubTask(SubTaskEntity subTaskEntity) {
        // 删除任务环节实例
        this.subTaskNodeInstDao.deleteBySubTaskId(subTaskEntity.getId());
        // 删除附件表
        this.taskNodeFileDao.deleteBySubTaskId(subTaskEntity.getId());
        // 删除导出数据表
        this.electricCoreDataDao.deleteBySubTaskId(subTaskEntity.getId());
        // 更新子任务
        String oldElectricCoreCode = subTaskEntity.getElectricCoreCode();
        subTaskEntity.setElectricCoreCode(null);
        subTaskEntity.setElectricCoreType(null);
        subTaskEntity.setStatus(TaskStatusEnum.CREATED.getValue());
        subTaskEntity.setCurrentTaskNodeInstId(null);
        subTaskEntity.setUpdateBy(RequestTokenUtil.getRequestUser().getRequestUserId());
        subTaskEntity.setUpdateTime(new Date());
        subTaskEntity.setCompletionTime(null);
        this.subTaskDao.updateById(subTaskEntity);
        this.setOperations.remove(CommonConst.REDIS_ELECTRIC_CORE_CODE_SET_NAME, oldElectricCoreCode);

        // 如果主任务状态已经为完成，则更新为运行状态
        TaskEntity taskEntity = this.taskDao.selectById(subTaskEntity.getMainTaskId());
        if (Objects.nonNull(taskEntity) && TaskStatusEnum.COMPLETE.getValue().equals(taskEntity.getStatus())) {
            taskEntity.setStatus(TaskStatusEnum.RUNNING.getValue());
            taskEntity.setUpdateBy(RequestTokenUtil.getRequestUser().getRequestUserId());
            taskEntity.setUpdateTime(new Date());
            this.taskDao.updateById(taskEntity);
        }
        return ResponseDTO.succ();
    }

    /**
     * 完成子任务
     * @return
     */
    @Transactional(rollbackFor = Exception.class)
    public ResponseDTO<String> finishTask(SubTaskEntity subTaskEntity) {
        this.subTaskDao.updateByIdIgnoreEmptyValue(subTaskEntity);

        SubTaskQueryDTO subTaskQueryDTO = new SubTaskQueryDTO();
        subTaskQueryDTO.setMainTaskId(subTaskEntity.getMainTaskId());
        List<SubTaskEntity> subTaskEntityList = this.subTaskDao.queryList(subTaskQueryDTO);

        // 所有子任务都完成则结束主任务
        boolean allSubTaskFinish = subTaskEntityList.stream().allMatch(e -> TaskStatusEnum.COMPLETE.getValue().equals(e.getStatus()));
        if (allSubTaskFinish) {
            TaskEntity taskEntity = this.taskDao.selectById(subTaskEntity.getMainTaskId());
            taskEntity.setStatus(TaskStatusEnum.COMPLETE.getValue());
            taskEntity.setCompletionTime(new Date());
            this.taskDao.updateByIdIgnoreEmptyValue(taskEntity);
        }
        return ResponseDTO.succ();
    }

    @Transactional(rollbackFor = Exception.class)
    public ResponseDTO<String> updateTask(SubTaskEntity subTaskEntity, SubTaskNodeInstAddDTO addDTO, Long nextTaskNodeInstId) {
        boolean isUpdateSubTask = false;
        boolean isUpdateElectricCoreCode = false;
        if (StrUtil.isEmpty(subTaskEntity.getElectricCoreCode()) || StrUtil.isEmpty(subTaskEntity.getElectricCoreType())) {
            subTaskEntity.setElectricCoreCode(addDTO.getElectricCoreCode());
            subTaskEntity.setElectricCoreType(addDTO.getElectricCoreType());
            isUpdateSubTask = true;
            isUpdateElectricCoreCode = StrUtil.isNotEmpty(addDTO.getElectricCoreCode()) ? true : false;
        }
        // 是否结束子任务（1. 用户显示指定完成 ）
        if (BooleanUtil.isTrue(addDTO.isFinish())) {
            subTaskEntity.setStatus(TaskStatusEnum.COMPLETE.getValue());
            subTaskEntity.setCompletionTime(new Date());
            isUpdateSubTask = true;
        }
        if (Objects.nonNull(nextTaskNodeInstId) && !nextTaskNodeInstId.equals(subTaskEntity.getCurrentTaskNodeInstId())) {
            subTaskEntity.setCurrentTaskNodeInstId(nextTaskNodeInstId);
            isUpdateSubTask = true;
        }
        if (isUpdateSubTask) {
            // 更新子任务
            subTaskEntity.setUpdateTime(new Date());
            subTaskEntity.setUpdateBy(RequestTokenUtil.getRequestUser().getRequestUserId());
            this.subTaskDao.updateByIdIgnoreEmptyValue(subTaskEntity);

            if (isUpdateElectricCoreCode) {
                this.setOperations.add(CommonConst.REDIS_ELECTRIC_CORE_CODE_SET_NAME, subTaskEntity.getElectricCoreCode());
            }
        }

        // 完成一个子任务则校验是否所有子任务已经完成，完成则同时完成主任务
        if (TaskStatusEnum.COMPLETE.getValue().equals(subTaskEntity.getStatus())) {
            SubTaskQueryDTO subTaskQueryDTO = new SubTaskQueryDTO();
            subTaskQueryDTO.setMainTaskId(subTaskEntity.getMainTaskId());
            List<SubTaskEntity> subTaskEntityList = this.subTaskDao.queryList(subTaskQueryDTO);
            boolean allSubTaskFinish = subTaskEntityList.stream()
                    .allMatch(e -> TaskStatusEnum.COMPLETE.getValue().equals(e.getStatus()));
            if (allSubTaskFinish) {
                TaskEntity taskEntity = this.taskDao.selectById(subTaskEntity.getMainTaskId());
                taskEntity.setStatus(TaskStatusEnum.COMPLETE.getValue());
                this.taskDao.updateByIdIgnoreEmptyValue(taskEntity);
            }
        }

        return ResponseDTO.succ();
    }
}
